package com.doraz.orb.methods;

import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.Header;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.cookie.Cookie;
import org.apache.http.cookie.CookieOrigin;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.cookie.BrowserCompatSpec;
import org.apache.http.impl.cookie.CookieSpecBase;
import org.apache.http.message.BasicNameValuePair;

import com.doraz.orb.Constants;

import android.util.Log;
import android.webkit.CookieManager;

public class MethodFactory {
	
	private static MethodFactory factory;
	private Cookie sessionCookie;
	private int speed = 0;
	private int height = 0;
	private int width = 0;
	private int statusCode = 0;
	private String message = null;
	private final static String TAG = "MethodFactory";
	
	private final static String LOGIN_URL = Constants.BASE_URL_SECURE+"/xml/session.login";
	private final static String HOST = "api.orb.com";
	private final static int PORT = 80;
	
	/**
	 * Prevent instantiation
	 */
	private MethodFactory() {
		sessionCookie = null;
	}
	
	
	public static MethodFactory getInstance() {
		if(factory == null) {
			factory = new MethodFactory();
		}
		
		return factory;
	}
	
	/**
	 * Logs a user in
	 * 
	 * @param username
	 * @param password
	 * @return
	 */
	public InputStream login(String username, String password) {
		InputStream in = null;
		try {
			HttpClient httpclient = new DefaultHttpClient();
			HttpPost httpPost = new HttpPost(LOGIN_URL);
			ArrayList<BasicNameValuePair> nameValuePairs = new ArrayList<BasicNameValuePair>();
			nameValuePairs.add(new BasicNameValuePair("apiKey", Constants.API_KEY));
			nameValuePairs.add(new BasicNameValuePair("l", username));
			nameValuePairs.add(new BasicNameValuePair("password", password));
			
			//Set the optional values
			if(speed > 0) {
				nameValuePairs.add(new BasicNameValuePair("speed", ""+speed));
			}
			if(width > 0) {
				nameValuePairs.add(new BasicNameValuePair("width", ""+width));
			}
			if(height > 0) {
				nameValuePairs.add(new BasicNameValuePair("height", ""+height));
			}
			
			//Set the params
			httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
			
			//Execute the request
			HttpResponse response = httpclient.execute(httpPost);
			
			//Get the session cookie
			Cookie sessionCookie = null;			
			Header[] allHeaders = response.getAllHeaders();
			CookieOrigin origin = new CookieOrigin(HOST, PORT, LOGIN_URL, true);
			CookieSpecBase cookieSpecBase = new BrowserCompatSpec();
			for (Header header : allHeaders) {
				List<Cookie> parse = cookieSpecBase.parse(header, origin);
				for (Cookie cookie : parse) {
					if (cookie.getValue() != null & !cookie.getValue().equals("")) {
						sessionCookie = cookie;
						Log.w(TAG, "Got the cookie");
					}
				}
			}
			
			if(sessionCookie == null) {
				Log.w(TAG, "FAILED TO GET COOKIE");
			}
			
			//Save the last response codes/messages
			statusCode = response.getStatusLine().getStatusCode();
			message = response.getStatusLine().getReasonPhrase();
			
			//Set the input stream
			in = response.getEntity().getContent();
			
		} catch(Exception e) {
			Log.w(TAG, "Exception: "+e.getMessage());
		}
		
		return in;
	}
	
	/**
	 * Calls a method
	 * 
	 * @param method	the method to call
	 * @return			the InputStream
	 */
	public InputStream callMethod(OrbMethod method) {
		InputStream in = null;
		
		try {
			String url = method.getURL();
			if(url == null) {
				Log.w(TAG, "Received a null URL for method "+method.getMethodName());
				throw new IllegalArgumentException("Received a null URL for method "+method.getMethodName());
			}
			
			HttpGet httpGet = new HttpGet(url);
			HttpClient httpclient = new DefaultHttpClient();
			
			//Set the session cookie
			if(sessionCookie != null) {
				CookieSpecBase cookieSpecBase = new BrowserCompatSpec();
				List<Cookie> cookies = new ArrayList<Cookie>();
				cookies.add(sessionCookie);
				List<Header> cookieHeader = cookieSpecBase.formatCookies(cookies);
				httpGet.setHeader(cookieHeader.get(0));
			}
			
			//Execute the request
			HttpResponse response = httpclient.execute(httpGet);
			
			//Save the last response codes/messages
			statusCode = response.getStatusLine().getStatusCode();
			message = response.getStatusLine().getReasonPhrase();
			
			//Set the input stream
			in = response.getEntity().getContent();
		}
		catch(Exception e) {
			Log.w(TAG, "Error Calling method: "+method.getURL());
			Log.w(TAG, "Exception: "+e.getMessage());
		}
		
		return in;
	}
}
